04. The Call Stack
Single Threading
You might've heard that JavaScript is single-threaded but what does that mean? According to Wikipedia, single-threading is:
the processing of one command at a time (source)
Ok, so JavaScript can "process" one command at a time. The opposite of single-threading, is multithreading. There are numerous pros and cons to both which we won't be getting into (feel free to check out the Wikipedia article on Threading for more info about the pros and cons). We're going to take a look at JavaScript's single-threaded model and how/why we should write our code to take advantage of it.
Let's look at some code:
function addParagraph() {
const para = document.createElement('p');
para.textContent = 'JavaScript is single threaded!';
document.body.appendChild(para);
}
function appendNewMessage() {
const para = document.createElement('p');
para.textContent = "Isn't that cool?";
document.body.appendChild(para);
}
addParagraph();
appendNewMessage();
Keeping JavaScript's single-threaded nature in mind (meaning it can only perform one task at a time), let's break down this code into the order it will run:
- the
addParagraph()function is declared on line 1 - the
appendNewMessage()function is declared on line 6 addParagraph()is called on line 13- execution moves into the function and executes all three lines in order
- now that the function is finished, execution returns to where it was called
- the
appendNewMessage()function is called on line 14- execution moves into the function and executes all three lines in order
- now that the function is finished, execution returns to where it was called
- the program ends because all lines of code have been executed
Hopefully, the order that this code executed in wasn't surprising. There are a couple of things I particularly want you to pay attention to. First, is the run-to-completion nature of the code. When addParagraph() is invoked on line 13, all of the code in the function gets executed: it doesn't just execute some lines and leave other lines to be executed later. The entire block of code is run. A second thing I want to point out is that addParagraph() is invoked, runs, and finishes before appendNewMessage() is invoked (including a possible reflow and repaint); JavaScript doesn't execute multiple lines/functions at the same time (this is single-threading…processing one command at a time!).
I have a question for you - once addParagraph() has been invoked and it runs the lines of code inside the addParagraph() function, how does it know to go back to appendNewMessage()? How does it keep track of that?
What if we changed this code slightly to create nested functions:
function addParagraph() {
const para = document.createElement('p');
para.textContent = 'JavaScript is single threaded!';
appendNewMessage();
document.body.appendChild(para);
}
function appendNewMessage() {
const para = document.createElement('p');
para.textContent = "Isn't that cool?";
document.body.appendChild(para);
}
addParagraph();
Notice that the call to appendNewMessage() is located inside the addParagraph() function. First, addParagraph() is invoked. Then appendNewMessage() is invoked on line 5. Once appendNewMessage() has finished running, execution returns and finishes running the last line of code in the addParagraph() function…but how does it know how to do that? How does the JavaScript engine know where it left off and how to get back to it?
The Call Stack
The JavaScript engine keeps a call stack (basically a list) of the functions that are running. When a function is invoked, it is added to the list. When all of the code inside a function has been run, then the function is removed from the call stack. The cool part about a call stack is that a function doesn't have to complete before another function is added to the call stack.
Let's see how this works!
L4 - 24 - Callstack V1
SOLUTION:
- 2
Use this code for the following question.
function dolphins () {
// stop here
return 'llamas';
}
function rhinos () {
var y = 'no';
return penguins();
}
function penguins () {
return camels();
}
function camels () {
return dolphins();
}
rhinos()
QUIZ QUESTION::
Put the function names in the correct order they would appear when the // stop here comment is reached. Remember to put the oldest/initial at the bottom of the stack. Assume there is no "<main>"/default frame.
ANSWER CHOICES:
|
Order of Stack |
Function Name |
|---|---|
dolphins |
|
penguins |
|
camels |
|
rhinos |
SOLUTION:
|
Order of Stack |
Function Name |
|---|---|
|
dolphins |
|
|
penguins |
|
|
camels |
|
|
rhinos |
The Call Stack Recap
In this section, we looked at how JavaScript is a single-threaded programming language, which means it can only execute one thing at a time. We looked at how JavaScript keeps track of what functions are running by using the Call Stack.
Further Research
- Call stack on MDN
- Call stack on Wikipedia